home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_08_12 / 8n12085a < prev    next >
Text File  |  1990-08-28  |  5KB  |  172 lines

  1. /* kserver.c - task Keyboard Server interrupt driven */
  2.  
  3. #include <synrtx.h>
  4. #include <ascii.h>
  5.  
  6. #define BEEP    8
  7. #define NCHARS  80
  8. #define NOBODY  0
  9. #define EOI     0x20
  10.  
  11. static word buffer[NCHARS], nCharsIn, charToSend, charToReceive;
  12. static task_t  ksid, owner;
  13. static msg_t  msg;
  14.  
  15. /* handler numbers */
  16. #define ACQUIRE     0
  17. #define RELEASE     1
  18. #define HIT         2
  19. #define EXCEPTION   3
  20. #define GETCHAR     4
  21.  
  22. #define  PORT_A  0x60  /* 8255 */
  23. #define  PORT_B  0x61  
  24.  
  25. static char kbdTab[] = {
  26. NUL,ESC,'1','2','3','4','5','6','7','8','9','0','-','=',  /* 00-13 */
  27. BS,HT,'q','w','e','r','t','y','u','i','o','p','[',']',CR, /* 14-28 */
  28. 0,'a','s','d','f','g','h','j','k','l',';','\"','`',       /* 29-41 */
  29. 0,'\\','z','x','c','v','b','n','m',',','.','/',0,'*',     /* 34-55 */
  30. 0,' ',0 };                                                /* 56-58 */
  31.  
  32. static byte  code, status;
  33. static bool  bufferFull;
  34.  
  35. /* Hardware handler Keyboard for interrupt vector 9 */
  36. static handler Keyboard(void) {
  37.     /* disable keyboard interrupt to not overwrite interrupt stack */
  38.     dev_enable(DISABLE, 1, KEYBOARD);
  39.     cpu_enable();       /* allow further interrupts */
  40.  
  41.     code   = dev_byte(PORT_A);
  42.     status = dev_byte(PORT_B);
  43.     dev_setByte(status | 0x80, PORT_B);  /* send ack _/^\_ to kbd */
  44.     dev_setByte(status & 0x7F, PORT_B);
  45.  
  46.     if (code < 0x80   &&   kbdTab[code]   &&   !bufferFull) {
  47.         msg.value.w = (word)kbdTab[code];
  48.         /* interrupt KeyboardServer.GetChar */
  49.         task_interrupt(&msg);
  50.     }
  51.     /* keep all interrupts disable for the EOI and Exit */
  52.     cpu_Disable();
  53.     dev_setByte(EOI, 0x20); 
  54.     dev_enable(ENABLE, 1, KEYBOARD);
  55. }
  56.  
  57. static handler Acquire(msg_t *msg_p) {
  58.     register task_t caller = msg_p->srcTid;
  59.     register task_t self   = msg_p->dstTid;
  60.  
  61.     owner      = caller;
  62.     charToSend = charToReceive = nCharsIn = 0;
  63.     bufferFull = FALSE;
  64.  
  65.     /* interrupt caller.Grant */
  66.     msg_p->srcTid = self;
  67.     msg_p->dstTid = caller;
  68.     msg_p->dstHid = 0; /* GRANT = 0 */
  69.     msg_p->type   = msg_type_SYNC;
  70.     task_interrupt(msg_p);
  71. }
  72.      
  73. static handler Release(msg_t *msg_p) {
  74.     register task_t caller = msg_p->srcTid;
  75.     register task_t self   = msg_p->dstTid;
  76.  
  77.     if (owner == caller) {
  78.         owner = NOBODY;
  79.         /* BufferFull is set to TRUE to avoid any software interrupts */
  80.         bufferFull = TRUE;
  81.     } else {
  82.         /* interrupt self.Exception(caller) */
  83.         msg_p->srcTid  = msg_p->dstTid = self;
  84.         msg_p->dstHid  = EXCEPTION;
  85.         msg_p->type    = msg_type_WORD;
  86.         msg_p->value.w = (word)caller;
  87.         task_interrupt(msg_p);
  88.     }
  89. }
  90.  
  91. static handler Hit(msg_t *msg_p) {
  92.     register task_t caller = msg_p->srcTid;
  93.     register task_t self   = msg_p->dstTid;
  94.     register word c;
  95.  
  96.     if (owner == caller) {
  97.         if (nCharsIn == 0)        /* buffer empty ? */
  98.             c = 0;
  99.         else {
  100.             c = buffer[charToSend] | 0x0100;
  101.             charToSend = (charToSend + 1) % NCHARS;
  102.             nCharsIn--;
  103.             bufferFull = FALSE;
  104.         }
  105.  
  106.         /* interrupt caller.GetChar(character) */
  107.         msg_p->srcTid  = msg_p->dstTid;
  108.         msg_p->dstTid  = caller;
  109.         msg_p->dstHid  = 1; /* GetChar = 1 */
  110.         msg_p->type    = msg_type_WORD;
  111.         msg_p->value.w = c;
  112.         task_interrupt(msg_p);
  113.     } else {
  114.         /* interrupt self.Exception(caller) */
  115.         msg_p->srcTid  = msg_p->dstTid = self;
  116.         msg_p->dstHid  = EXCEPTION;
  117.         msg_p->type    = msg_type_WORD;
  118.         msg_p->value.w = (word)caller;
  119.         task_interrupt(msg_p);
  120.     }
  121. }
  122.  
  123. static handler Exception(msg_t *msg_p) {
  124.     io_putf("Illegal Access to KeyboardServer by Task #%w", msg_p->value.w);
  125. }
  126.  
  127. static handler GetChar(msg_t *msg_p) {
  128.     if (nCharsIn == NCHARS)  /* buffer full ? */ {
  129.         /* then, ignore the character (stops int from hard) */
  130.         io_puts("\nKeyboardServer: buffer full !\n");            
  131.         bufferFull = TRUE;
  132.     } else {
  133.         buffer[charToReceive] = msg_p->value.w;
  134.         charToReceive = (charToReceive + 1) % NCHARS;
  135.         nCharsIn++;
  136.     }
  137. }
  138.  
  139. task KeyboardServer(void) {
  140.     register word ps;
  141.  
  142.     ps = cpu_saveAndDisable();
  143.     ksid = task_self();
  144.  
  145.     /* Install Keyboard hardware handler as the ISR for interrupt vector 9 */
  146.     cpu_setHandler(INT9_KEYBOARD, Keyboard);
  147.  
  148.     /* Install software handlers */
  149.     task_setHandler(5, Acquire, Release, Hit, Exception, GetChar);
  150.  
  151.     charToSend = charToReceive = nCharsIn = 0;
  152.     /* 
  153.      * The KeyboardServer cannot receive characters while it is not yet
  154.      * acquired, but should wait until a "client" gets it.
  155.      * BufferFull is set to TRUE to avoid any software interrupts.
  156.      */
  157.     bufferFull = TRUE; 
  158.     msg.srcTid = msg.dstTid = ksid;
  159.     msg.dstHid = GETCHAR;
  160.     msg.type   = msg_type_WORD;
  161.     cpu_restore(ps);
  162.     loop {
  163.         /* enable wait Acquire */
  164.         task_enableWait(NO_TIMEOUT, 1, ACQUIRE);
  165.  
  166.         do /* enable wait GetChar, Hit, Release, Exception */
  167.             task_enableWait(NO_TIMEOUT,4,GETCHAR,HIT,RELEASE,EXCEPTION);
  168.         while (owner != NOBODY);
  169.     }
  170. }
  171.  
  172.